import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import glob from 'fast-glob'
import { genKey } from './genKey.js'
import { readJSON, writeJSON } from './utils.js'
import { extractCode } from './extractCode.js'
import { extractPure } from './extractPure.js'
import type { Stats } from './types.js'
import chalk from 'chalk'

const CHINESE = /[\u4e00-\u9fa5]/
const QUOTE_RE =
  /(["'`])((?:(?!\1)[\s\S])*?[\u4e00-\u9fa5]+(?:(?!\1)[\s\S])*?)\1/g
const MUSTACHE_RE = /\{\{[\s\S]*?([\u4e00-\u9fa5]+[\s\S]*?)\}\}/g

export async function performExtract(
  srcDir: string,
  outFile: string,
  ext: string[] = ['vue', 'js', 'jsx', 'ts', 'tsx'],
  enFile?: string
): Promise<Stats> {
  const exists = readJSON<Record<string, string>>(outFile)
  const newTexts = new Map<string, string>()
  const patterns = ext.map((e) => `**/*.${e}`)

  const files = await glob(patterns, {
    cwd: srcDir,
    ignore: ['node_modules/**', 'lang/**'],
  })

  function add(text: string) {
    if (!text || !CHINESE.test(text) || text.includes('$')) return
    extractPure(text).forEach((cn) => {
      const key = genKey(cn)
      if (!exists[key] && !newTexts.has(key)) newTexts.set(key, cn)
    })
  }

  files.forEach((f) => {
    const full = resolve(srcDir, f)
    const content = readFileSync(full, 'utf-8')
    const realCode = extractCode(content) // 非注释代码

    let m: RegExpExecArray | null
    while ((m = QUOTE_RE.exec(realCode)) !== null)
      extractPure(m[2].trim()).forEach(add)
    while ((m = MUSTACHE_RE.exec(realCode)) !== null)
      extractPure(m[1].trim()).forEach(add)
  })

  writeJSON(outFile, { ...exists, ...Object.fromEntries(newTexts) })

  /* 自动翻译英文 */
  if (newTexts.size && enFile) {
    const { translateBatch } = await import('./translate.js')
    const enOld = readJSON<Record<string, string>>(enFile)
    const toTranslate = Array.from(newTexts.entries()).filter(
      ([, cn]) => !enOld[cn]
    )
    if (toTranslate.length) {
      console.log(chalk.cyan(`🌍  Translating ${toTranslate.length} items...`))
      const cn2en = await translateBatch(toTranslate.map(([, cn]) => cn))
      for (const [key, cn] of toTranslate) {
        enOld[key] = cn2en[cn] || '' // 空串留人工补
      }
      writeJSON(enFile, enOld)
      console.log(chalk.green(`✅  Updated en-US → ${enFile}`))
    }
  }

  return { newKeys: newTexts.size }
}
